package com.sparrow.common.buff;

import com.sparrow.common.buff.domain.Buff;
import com.sparrow.common.buff.listener.BuffListener;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Buff容器
 */
public class BuffBox {
    /**
     * buff唯一id -> Buff实例
     */
    private final Map<Long, Buff> buffMap = new ConcurrentHashMap<>();
    /**
     * buff监听器
     */
    private final List<BuffListener> listeners = new ArrayList<>();

    public void addListener(BuffListener listener) {
        listeners.add(listener);
    }

    public void removeListener(BuffListener listener) {
        listeners.remove(listener);
    }

    /**
     * 添加Buff
     * 叠加规则：
     * 1配置没叠加的应该直接存放
     * 2配置没叠加的但是要把旧的替换掉
     * 3配置了叠加的叠加到相同configId上
     *
     * @param newBuff
     */
    public void addBuff(Buff newBuff) {
        long now = System.currentTimeMillis();
        Buff existing = getBuffByConfigId(newBuff.getConfigId());
        if (existing != null) {
            if (existing.canStack()) {
                existing.stack(now);
            } else {
                if (newBuff.canReplace()) {
                    removeBuff(existing);
                    addNewBuff(newBuff);
                } else {
                    addNewBuff(newBuff);
                }
            }
        } else {
            addNewBuff(newBuff);
        }
    }

    public Buff getBuffByConfigId(int configId) {
        return buffMap.values().stream().filter(e -> e.getConfigId() == configId).findFirst().orElse(null);
    }

    /**
     * 移除buff
     * @param buff
     */
    public void removeBuff(Buff buff) {
        buff.onExpire();
        buffMap.remove(buff.getUniqueId());
    }

    private void addNewBuff(Buff newBuff) {
        buffMap.put(newBuff.getUniqueId(), newBuff);
        newBuff.onStart();
        notifyBuffAdded(newBuff);
    }

    private void notifyBuffAdded(Buff buff) {
        for (BuffListener listener : listeners) {
            listener.onBuffAdded(buff);
        }
    }

    private void notifyBuffExpire(Buff buff) {
        for (BuffListener listener : listeners) {
            listener.onBuffExpire(buff);
        }
    }

    /**
     * 定时器更新
     * @param now
     */
    public void update(long now) {
        for (Buff buff : buffMap.values()) {
            buff.onTick(now);
        }
        checkExpired(now);
    }

    public void checkExpired(long now) {
        Iterator<Map.Entry<Long, Buff>> it = buffMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Long, Buff> entry = it.next();
            Buff buff = entry.getValue();
            if (buff.isExpired(now)) {
                it.remove();
                buff.onExpire();
                notifyBuffExpire(buff);
            }
        }
    }
}
